<script>
export default {
  name: 'Table',
  props: {
    rowKey: {
      type: String,
      default: 'id'
    },
    height: {
      type: String,
      default: '100%'
    },
    expand: {
      type: Boolean,
      default: false
    },
    searchData: {
      type: Object,
      default: () => {}
    },
    tableData: {
      type: Array,
      default: () => []
    },
    tableLabel: {
      type: Array,
      default: () => []
    },
    tableTotalSize: {
      type: Number,
      default: null
    },
    editMode: {
      type: Boolean,
      default: false
    },
    defaultExpandAll: {
      type: Boolean,
      default: false
    },
    paginate: {
      type: Boolean,
      default: true
    },
    sortByRefresh: {
      type: Boolean,
      default: true
    }
  },
  data() {
    return {
      originalTableData: [],
      formatTableData: []
    }
  },
  // watch: {
  //   tableData(val) {
  //     this.formatFunction(val)
  //   }
  // },
  mounted() {
    this.getTableData()
    this.tableWidthCompute()
  },
  methods: {
    // 获取修改后的值
    getInputValue() {
      return this.formatTableData
    },
    // 当行数据修改后,回调当行数据
    inputChange(val, item) {
      this.$emit('inputChange', item)
    },
    // 输入限制
    inputLimit(value, editParameter, row, prop) {
      if (editParameter) {
        if (editParameter.type === 'int') {
          value = value.replace(/[^\d.]/g, '') // 清除“数字”和“.”以外的字符
          value = value.replace(/\.{2,}/g, '.') // 只保留第一个. 清除多余的
          value = value.replace('.', '$#$').replace(/\./g, '').replace('$#$', '.')
          value = value.replace(/^(\-)*(\d+)\.(\d\d).*$/, '$1$2.$3') // 只能输入两个小数
          if (value.indexOf('.') < 0 && value !== '') {
            // 以上已经过滤，此处控制的是如果没有小数点，首位不能为类似于 01、02的金额
            value = parseFloat(value)
          }
          row[prop] = value
        }
      }
    },
    // 深拷贝数组
    cloneArr(arr) {
      const newArr = []
      for (const arrItem of arr) {
        newArr.push(arrItem)
      }
      return newArr
    },
    // 格式化函数
    formatFunction(res) {
      const filtersList = []
      this.originalTableData = JSON.parse(JSON.stringify(res))
      this.formatTableData = JSON.parse(JSON.stringify(res))
      // 获取需格式化的项与格式化数据
      if (this.formatTableData.length > 0) {
        for (const key in this.formatTableData[0]) {
          for (const label of this.tableLabel) {
            if (label.formatter && key === label.prop) {
              const obj = {
                key: key,
                formatter: label.formatter
              }
              filtersList.push(obj)
            }
          }
        }
      }
      // 循环格式化
      for (const filters of filtersList) {
        for (const index in this.formatTableData) {
          this.formatData(index, filters)
        }
      }
    },
    // 对单项数据进行格式化
    formatData(index, filters) {
      for (const item of filters.formatter) {
        if (this.formatTableData[index][filters.key] === item.value) {
          this.formatTableData[index][filters.key] = item.label
        }
      }
    },
    setCurrentData(index, data) {
      this.formatTableData.splice(index, 1, data)
      this.$refs.tableComponent.setCurrentRow(this.formatTableData[index])
    },
    // 获取表格数据
    getTableData() {
      this.$emit('getTableData', (res) => {
        this.formatFunction(res)
        this.$nextTick(() => {
          // this.$refs.tableComponent.clearSelection()
          if (this.$refs.tableComponent) {
            if (this.formatTableData.length > 0) {
              this.$refs.tableComponent.setCurrentRow(this.formatTableData[0])
            }
            this.$refs.tableComponent.doLayout()
          }
        })
      })
    },
    // 排序回调函数
    sortChange({ column, prop, order }) {
      if (this.sortByRefresh) {
        if (column.sortable === 'custom') {
          this.searchData.sort = {}
          if (order === 'ascending') {
            this.searchData.sort[prop] = 'asc'
          } else if (order === 'descending') {
            this.searchData.sort[prop] = 'desc'
          } else {
            this.searchData.sort[prop] = ''
          }
        } else {
          if (order === 'ascending') {
            this.searchData.sort[prop] = 'asc'
          } else if (order === 'descending') {
            this.searchData.sort[prop] = 'desc'
          } else {
            this.searchData.sort[prop] = ''
          }
        }

        this.getTableData()
      }
    },
    // 复选框回调函数
    handleSelectionChange(val) {
      this.$emit('handleSelectionChange', val)
    },
    // 点击行函数
    rowClick(row) {
      // 点击行就打开折叠
      for (const item of this.formatTableData) {
        if (item[this.rowKey] === row[this.rowKey]) {
          this.$refs.tableComponent.toggleRowExpansion(item)
        }
        // else {
        //   this.$refs.tableComponent.toggleRowExpansion(item, false)
        // }
      }
    },
    // 点击行回调函数
    rowClickChange(val) {
      this.getCurrentRow(val, this.originalTableData)
    },
    // 递归找当前行
    getCurrentRow(val, tableData) {
      for (const item of tableData) {
        if (val[this.rowKey] === item[this.rowKey]) {
          this.$emit('rowClickChange', item)
        } else if (item.children && item.children.length > 0) {
          this.getCurrentRow(val, item.children)
        }
      }
    },
    // 页面条数回调函数
    pageSizeChange(val) {
      this.searchData.pageSize = val
      this.getTableData()
    },
    // 页码修改回调函数
    pageChange(val) {
      this.searchData.currentPage = val
      this.getTableData()
    },
    // 展开行回调函数
    expandChange(row) {
      this.$emit('expandChange', row)
    },
    // 复选框函数
    toggleSelection(rows) {
      if (rows) {
        rows.forEach((row) => {
          this.$refs.tableComponent.toggleRowSelection(row)
        })
      } else {
        this.$refs.tableComponent.clearSelection()
      }
    },
    // 过滤选择前端处理函数
    filterHandler(value, row, column) {
      // const property = column['property']// 选择的键名
      // this.searchData.params[property] = value
      // this.$emit('test')
      return true
    },
    // 过滤选择修改回调函数
    filterChange(filters) {
      for (const key in filters) {
        this.searchData.params[key] = filters[key]
        this.searchData.currentPage = 1
        this.getTableData()
      }
    },
    // 自适应table宽度函数
    tableWidthCompute() {
      const _self = this
      this.$nextTick(() => {
        var oldWidth = this.$refs.tableDiv.offsetWidth
        for (const index in this.tableLabel) {
          if (this.tableLabel[index].width) {
            this.tableLabel[index].width = (this.tableLabel[index].width / 1920) * document.body.clientWidth
          }
        }
        const arr = JSON.parse(JSON.stringify(_self.tableLabel))
        var elementResizeDetectorMaker = require('element-resize-detector') // 导入
        var erd = elementResizeDetectorMaker()
        erd.listenTo(this.$refs.tableDiv, function (element) {
          for (const index in arr) {
            const width = arr[index].width / oldWidth
            if (
              _self.tableLabel[index].minWidth &&
              element.offsetWidth * width < _self.tableLabel[index].minWidth
            ) {
              _self.tableLabel[index].width = _self.tableLabel[index].minWidth
              continue
            }
            if (
              _self.tableLabel[index].maxWidth &&
              element.offsetWidth * width > _self.tableLabel[index].maxWidth
            ) {
              _self.tableLabel[index].width = _self.tableLabel[index].maxWidth
              continue
            }
            if (_self.tableLabel[index].width) {
              _self.tableLabel[index].width = element.offsetWidth * width
            }
          }
          _self.$nextTick(() => {
            if (_self.$refs.tableComponent) {
              _self.$refs.tableComponent.doLayout()
            }
          })
        })
      })
    },
    // 添加行样式
    tableRowClassName({ row, rowIndex }) {
      let className
      this.$emit('tableRowClassName', { row, rowIndex }, (val) => {
        className = val
      })
      return className
    },
    doLayout() {
      this.$refs.tableComponent.doLayout()
    }
  },
  render(h) {
    let tableHight = this.paginate ? 'hasPaginate' : 'noPaginate'
    return (
      <div id="tableDiv" ref="tableDiv" class="table-index" class={tableHight}>
        <el-table
          ref="tableComponent"
          row-key={this.rowKey}
          data={this.formatTableData}
          tooltip-effect="dark"
          class="tableStyle"
          // stripe={true}
          height={this.height}
          // v-bind={this.$attrs}
          // v-on={this.$listeners}
          highlight-current-row
          default-expand-all={this.defaultExpandAll}
          header-cell-style={{ background: '#fafafa', height: '54px', fontSize: '15px' }}
          row-style={{ padding: '0px' }}
          tree-props={{ children: 'children', hasChildren: 'hasChildren' }}
          on-filter-change={this.filterChange}
          on-sort-change={this.sortChange}
          on-current-change={this.rowClickChange}
          on-row-click={this.rowClick}
          on-selection-change={this.handleSelectionChange}
          on-expand-change={this.expandChange}
          row-class-name={this.tableRowClassName}
        >
          {this.tableLabel.map((item, index) => {
            var tableColumnProp = {
              key: index,
              prop: item.prop,
              sortable: item.sortable,
              label: item.label,
              width: item.width,
              showOverflowTooltip: item.showOverflowTooltip,
              fixed: item.fixed,
              filterMultiple: item.filterMultiple,
              align: item.align ?? 'left'
            }
            if (item.filters) {
              tableColumnProp['filters'] = item.filters
              tableColumnProp['columnKey'] = item.prop
              tableColumnProp['filterHandler'] = this.filterHandler
            }
            if (item.labelDisplay !== false) {
              switch (item.type) {
                case 'expand':
                  return (
                    <el-table-column type="expand">
                      {(props) => {
                        if (item.expandType === 'slot') {
                          return this.$scopedSlots['expandSlot']({ rowValue: props.row })
                        } else {
                          return (
                            <el-form label-position="left" inline class="demo-table-expand">
                              {this.tableLabel.map((label, index) => {
                                if (label.expandDisplay !== false && label.type !== 'expand') {
                                  return (
                                    <el-form-item
                                      key={label.prop}
                                      label={label.label + '：'}
                                      style={{ width: label.expandWidth ? label.expandWidth : '100%' }}
                                    >
                                      <span>{props.row[label.prop]}</span>
                                    </el-form-item>
                                  )
                                }
                              })}
                            </el-form>
                          )
                        }
                      }}
                    </el-table-column>
                  )
                case 'selection':
                  if (item.show) {
                    return (
                      <el-table-column key={index} type={item.type} width={item.width} reserve-selection={true} />
                    )
                  }
                  break
                case 'index':
                  if (item.show) {
                    return (
                      <el-table-column
                        key={index}
                        align={item.align}
                        label={item.label}
                        type="index"
                        width="60px"
                      />
                    )
                  }
                  break
                default:
                  return (
                    <el-table-column
                      {...{ props: tableColumnProp }}
                      scopedSlots={{
                        header: (props) => {
                          let label = ''
                          if (this.$scopedSlots[item.prop + 'Label'] && item.labelScope) {
                            label = this.$scopedSlots[item.prop + 'Label']({ labelValue: item.label })
                          } else {
                            label = item.label
                          }
                          return label
                        },
                        default: (scope) => {
                          switch (item.type) {
                            case 'image':
                              return (
                                <viewer images={scope.row[item.prop]}>
                                  {this.scope.row[item.prop].map((src) => {
                                    ;<img key={src} src={src} class="imgTable" />
                                  })}
                                </viewer>
                              )
                            case 'tag':
                              for (const tag of item.tagOptions) {
                                if (tag.value === scope.row[item.prop]) {
                                  return (
                                    <div align="center" class={'tableTag' + ' ' + tag.className}>
                                      {scope.row[item.prop]}
                                    </div>
                                  )
                                }
                              }
                              return <el-tag>{scope.row[item.prop]}</el-tag>
                            case 'scope':
                              if (this.$scopedSlots[item.prop]) {
                                var scopeDiv = this.$scopedSlots[item.prop]({ rowValue: scope.row })
                              }
                              return scopeDiv
                            default:
                              if (this.editMode) {
                                return (
                                  <el-input
                                    v-model={scope.row[item.prop]}
                                    on-change={(val) => this.inputChange(val, scope.row)}
                                    disabled={item.editParameter ? item.editParameter.disabled : false}
                                    on-input={(val) => {
                                      this.inputLimit(val, item.editParameter, scope.row, item.prop)
                                    }}
                                    class="editInput"
                                  />
                                )
                              } else {
                                return scope.row[item.prop]
                              }
                          }
                        }
                      }}
                    ></el-table-column>
                  )
              }
            }
          })}
        </el-table>
      </div>
    )
  }
}
</script>

<style lang="less" scoped>
/deep/.el-table__row--level-1 {
  background-color: #f7f7f7 !important;
}
.hasPaginate {
  height: calc(100% - 50px) !important;
}
.noPaginate {
  height: calc(100% - 20px) !important;
}
.table-index {
  padding: 10px 5px 20px 0px;
  position: relative;
  width: 100%;
  .tableStyle {
    width: 100%;
    margin-bottom: 20px;
  }
  .page {
    position: absolute;
    bottom: 0;
  }
  .imgTable {
    width: 50px;
    height: 50px;
  }
  .demo-table-expand {
    font-size: 0;
  }
  /deep/.demo-table-expand label {
    width: 110px;
    margin-left: 60px;
    color: #99a9bf;
  }
  .demo-table-expand /deep/ .el-form-item {
    margin-right: 0;
    margin-bottom: 0;
    width: 50%;
    text-align: left;
    float: left;
  }
  /deep/ .el-table__fixed-right {
    right: 3px !important;
  }
  // /deep/.el-table__fixed-body-wrapper{
  //   top:37px!important;
  // }
  /deep/ .el-table--striped tr/deep/ .el-table__row--striped td {
    background-color: #f2fafe;
  }
  /deep/ .el-table::before {
    height: 0px;
  }
  /deep/ .el-table td {
    padding: 3px;
    // text-align: center;
    height: 54px;
    color: #000000;
  }
  /deep/ .el-table th {
    padding: 8px 0px;
    // background-color:#fafafa;
    // text-align: center;
    // height:54px;
    color: #000000;
  }
  // /deep/ .el-table th {
  //   padding: 6px 0px;
  //   text-align: center;
  // }
  /deep/ .el-table__body-wrapper::-webkit-scrollbar {
    width: 2px;
  }
  /deep/ .el-table__body-wrapper::-webkit-scrollbar-thumb {
    border-radius: 2px;
    height: 2px;
    background: rgba(0, 0, 0, 0.2);
  }
  /deep/ .el-table__body-wrapper::-webkit-scrollbar-track {
    box-shadow: inset 0 0 5px #eee;
    border-radius: 2px;
    background: #eee;
  }
  /deep/ .el-table__body tr.current-row > td {
    background-color: #f1f6fd !important;
  }
}
/deep/.el-table .warning-row {
  background: #f0f9eb;
}

/deep/.el-table .success-row {
  background: #f0f9eb;
}
</style>
